#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <dirent.h>
#include <unistd.h>

#include <string.h>
#include <libgen.h>

 int mycpfile(const char *filepath, const char *dirpath){
    printf("cp %s -> %s/%s\n", filepath, dirpath, basename((char *)filepath));
    // 1. 验证dirpath目录是否存在 EXISTS(const char *path) -> errno_bash.h

    char dstpath[1024] = "";
    sprintf(dstpath, "%s/%s", dirpath, basename((char *)filepath));

    int fd1 = open(filepath, O_RDONLY); // 只读方式打开源文件
    int fd2 = open(dstpath, O_CREAT|O_WRONLY, 0755);
    if(fd1 < 2 || fd2 < 2) return -1;

    char buf[1024] = ""; // 数据缓冲区
    while(1){
        ssize_t len = read(fd1, buf, 1024);
        if(len > 0) {
            write(fd2, buf, len);
        }

        if(len < 1024) break; // 复制 完成
    }

    close(fd1);
    close(fd2);
 }

int mycpdir(const char *srcdir, const char *dstdir){
    printf("cp dir %s => %s\n", srcdir, dstdir);
    // 1. 验证srcdir是否为目录（opendir()）
    DIR *dir = opendir(srcdir);
    if(dir == NULL) return -1;

    // 2. 读取目录中所有子项 
    // struct dirent * readdir(DIR *) 函数 可以重复调用，
    //          每一次返回一个子项，直接为NULL表示所有子项读取结束了
    struct dirent *entry = NULL;
    while((entry = readdir(dir)) != NULL){  // 循环读取每一个子项
        // readdir 函数包含.和.., 要求不处理
        if(strncmp(".", entry->d_name, 1) == 0) continue;

        printf("%s(%d)\n",  entry->d_name,  entry->d_type);
        char srcpath[1024] = ""; // 源位置
        sprintf(srcpath, "%s/%s", srcdir, entry->d_name);
        char dstpath[1024] = ""; // 目标位置 
        sprintf(dstpath, "%s/%s", dstdir, basename((char *)srcdir) );

	// 创建目标目录中的源目录
    	if(opendir(dstpath) == NULL){
        	mkdir(dstpath, 0755); // 创建目录
    	}
       
        if(entry->d_type == DT_DIR){
            
            printf("-----start %s---------\n", srcpath);
            mycpdir(srcpath, dstpath); // 递归调用
            printf("-------end %s-------\n", srcpath);
            continue;
        }
        // 3. 复制文件子项到目标目录中
       mycpfile(srcpath, dstpath); 
    }
    
}

// ./cp3  -r  a  b
int main(int argc, char const *argv[])
{
    if(argc < 3) return -1;
    
    // 1. 读取-r参数，如果没有表示文件复制到目录中， 
    // 如果有-r或-R表示将源目录中所有项全部复制到目标目录

    char *srcdir = NULL; // 源目录
    char *destdir = NULL; // 目标目录

    if( strcmp("-r", argv[1] )==0  ||strcmp("-R", argv[1] )==0  ){
        srcdir = (char *)argv[2];
        destdir = (char *)argv[3];
    }else{
        srcdir = (char *)argv[1];
        destdir = (char *)argv[2];
    }

   
    
    mycpdir(srcdir, destdir);  // 2. 实现目录复制功能
    return 0;
}
